home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / REALITY / fastshadows / shad.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  22KB  |  1,016 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *  shad.c - 
  19.  *        A simple demo of real-time shadows.
  20.  *
  21.  *              Rolf van Widenfelt - July 1992
  22.  *                also hacked by
  23.  *              Paul Haeberli - 1992
  24.  *                thanks for help from
  25.  *            Mark Segal - 1992
  26.  *
  27.  *  $Revision: 1.9 $
  28.  */
  29. #include "stdio.h"
  30. #include "string.h"
  31. #include "math.h"
  32. #include "gl.h"
  33. #include "gl/device.h"
  34. #include "gl/image.h"
  35. #include "vect.h"
  36. #include "sgiobj.h"
  37.  
  38.  
  39. #define NLIGHTS     3
  40. #define SSIZE         512    /* must be power of 2 */
  41.  
  42. #define MENU_LIGHTVIEW        1
  43. #define MENU_EYEVIEW         2
  44. #define MENU_TOGGLECOLOR    3
  45. #define MENU_DISCO        4
  46. #define MENU_QUIT         5
  47.  
  48. #define SHADZNEAR    (0x0000)
  49. #define SHADZFAR    (0xffff)
  50. #define BACKCOLOR    (0x00202020)
  51.  
  52. #define WINTITLESTR "shad v2"
  53.  
  54. void shadowdisplacez(int mode);
  55. float *maketexprops(int dobicubic,int dofastread);
  56. float *maketevprops(int doalpha);
  57. void fromlight(float mat[4][4]);
  58. void myrectf(float x1,float y1,float x2,float y2,float z);
  59. char *computetitle();
  60.  
  61.  
  62. /*
  63.  *  mouse and trackball functions
  64.  */
  65.  
  66. typedef struct {
  67.     float ztrans;
  68.     float trotx, troty;
  69.     float wiggle; /* only used for disco mode */
  70. } TrackState;
  71.  
  72. float fgetmousex();
  73. float fgetmousey();
  74. void mytrackztrans(TrackState *ts,float z);
  75. void mytrackrot(TrackState *ts,float x,float y);
  76. void mytrackclick(TrackState *ts);
  77. void mytrackpoll(TrackState *ts);
  78. void mygettracktransform(TrackState *ts,float mat[4][4],float invmat[4][4]);
  79. void mygetdiscotransform(TrackState *ts,TrackState *ts2,float mat[4][4],float invmat[4][4]);
  80.  
  81.  
  82. int nobjs;
  83. sgiobj *obj[100];
  84. long wxsize; /* window size */
  85. long wysize;
  86. long wxorg; /* window origin */
  87. long wyorg;
  88. long menu, lmenu;
  89.  
  90. long ZNear;
  91. long ZFar;
  92.  
  93. int dolightview = 0;
  94. int dobicubic = 0;
  95. int dozdisplace = 1;
  96. int dofastread = 1;
  97. int coloredlights = 0;
  98. int dotracklight = 0; /* mouse button moves light */
  99. int curlightnum = 0; /* by default, light 1 is edited with left shift key hack */
  100. int dodrawlights = 1;
  101. int dodisco = 0;    /* "disco" mode */
  102. float disco_time;
  103. float disco_step = .03; /* time step per frame - should be a lot less than 1 */
  104.  
  105. float light_fov = 20.0;
  106. float light_near = 0.1;
  107. float light_far = 10.0;
  108.  
  109. float eyemat[4][4];
  110. float inveyemat[4][4];
  111. float eye_dz = -0.0015;
  112. float eye_fov = 20.0;
  113. float eye_near = 0.1;
  114. float eye_far = 10.0;
  115.  
  116. TrackState eyetrack[1];
  117.  
  118. typedef struct {
  119.     int texno;
  120.     float r, g, b;
  121.     TrackState track[1];
  122.     float mat[4][4];
  123.     float invmat[4][4];
  124.     float texm[4][4];
  125.     TrackState disco_track[1];
  126.     int disco_changed;
  127.     unsigned long smap[(SSIZE*SSIZE)/2];
  128. } LightBuffer;
  129.  
  130. void newshadowmap(LightBuffer *lightsource);
  131. void drawlight(LightBuffer *lt);
  132.  
  133. LightBuffer thelights[8];
  134. LightBuffer *curlight;
  135.  
  136. float Identity[4][4] = { 
  137.     1, 0, 0, 0,  
  138.     0, 1, 0, 0,  
  139.     0, 0, 1, 0,  
  140.     0, 0, 0, 1,
  141. };
  142.  
  143. /*
  144.  *  control latitude with rotx, longitude with roty.
  145.  *  translate away from object center with a negative tz.
  146.  */
  147. void
  148. setuplight(LightBuffer *lightsource,float rotx,float roty,float tz)
  149. {
  150.     pushmatrix();
  151.     loadmatrix(Identity);        
  152.     pushmatrix();
  153.     translate(0.0,0.0,tz);
  154.     rot(rotx,'x');
  155.     rot(roty,'y');
  156.     getmatrix(lightsource->mat);
  157.     popmatrix();
  158.     rot(-roty,'y');
  159.     rot(-rotx,'x');
  160.     translate(0.0,0.0,-tz);
  161.     getmatrix(lightsource->invmat);
  162.     popmatrix();
  163.     lightsource->track->ztrans = tz;
  164.     lightsource->track->trotx = rotx;
  165.     lightsource->track->troty = roty;
  166.     setlightcolor(lightsource,1.0,1.0,1.0);
  167. }
  168.  
  169. setlightcolor(lightsource,r,g,b)
  170. LightBuffer *lightsource;
  171. float r, g, b;
  172. {
  173.     lightsource->r = r;
  174.     lightsource->g = g;
  175.     lightsource->b = b;
  176. }
  177.  
  178. positionlight(invmat)
  179. float invmat[4][4];
  180. {
  181.     pushmatrix();
  182.     multmatrix(invmat);
  183.     mymakelight(0,0.0,0.0,0.0);
  184.     popmatrix();
  185. }
  186.  
  187. mymakelight(i,x,y,z)
  188. int i;
  189. float x, y, z;
  190. {
  191.     float li_desc[14];
  192.  
  193.     li_desc[0] = AMBIENT;
  194.     li_desc[1] = 0.1;
  195.     li_desc[2] = 0.1;
  196.     li_desc[3] = 0.1;
  197.     li_desc[4] = LCOLOR;
  198.     li_desc[5] = 1.0;
  199.     li_desc[6] = 1.0;
  200.     li_desc[7] = 1.0;
  201.     li_desc[8] = POSITION;
  202.     li_desc[9] = x;
  203.     li_desc[10] = y;
  204.     li_desc[11] = z;
  205.     li_desc[12] = 1.0; 
  206.     li_desc[13] = LMNULL;
  207.     lmdef(DEFLIGHT,i+1,14,li_desc);
  208.     lmbind(LIGHT0+i,i+1);
  209. }
  210.  
  211. lfunc(n)
  212. {
  213.     n = n-1;
  214.     if(n>=0 && n<NLIGHTS) {
  215.     if(curlight) 
  216.         newshadowmap(curlight);
  217.     curlight = &thelights[n];
  218.     dolightview = 1;
  219.     curlightnum = n; /* set current light for editing */
  220.     wintitle(computetitle());
  221.     }
  222.     return 0;
  223. }
  224.  
  225. #define LSCALE         (0.25)
  226. #define CLSCALE        (0.75)
  227. #define SPECSCALE     (0.50)
  228.  
  229. setlcolors()
  230. {
  231.     if(coloredlights) {
  232.     setlightcolor(thelights+0,1.0*CLSCALE,0.0*CLSCALE,0.0*CLSCALE);
  233.     setlightcolor(thelights+1,0.0*CLSCALE,0.6*CLSCALE,0.0*CLSCALE);
  234.     setlightcolor(thelights+2,0.0*CLSCALE,0.0*CLSCALE,1.0*CLSCALE);
  235.     setlightcolor(thelights+3,1.0*CLSCALE,0.5*CLSCALE,0.0*CLSCALE);
  236.     } else {
  237.     setlightcolor(thelights+0,1.0*LSCALE,1.0*LSCALE,0.6*LSCALE);
  238.     setlightcolor(thelights+1,1.0*LSCALE,0.6*LSCALE,1.0*LSCALE);
  239.     setlightcolor(thelights+2,0.6*LSCALE,1.0*LSCALE,1.0*LSCALE);
  240.     setlightcolor(thelights+3,1.0*LSCALE,1.0*LSCALE,1.0*LSCALE);
  241.     }
  242. }
  243.  
  244. main(argc, argv)
  245. int argc;
  246. char *argv[];
  247. {
  248.     short val;
  249.     int dev, i;
  250.     int firstobj = 1;
  251.     float *tevps;
  252.     int needredraw;
  253.     TrackState *track;
  254.  
  255.     if(argc<2) {
  256.     fprintf(stderr,"usage: shadow obj1.sgo [obj2.sgi obj3.sgo . . .\n");
  257.     exit(1);
  258.     }
  259.     if (!strcmp(argv[1],"-f")) {
  260.     dofastread = !dofastread;
  261.     firstobj++; /* hack for cmd line parsing */
  262.     printf("dofastread %d\n",dofastread);
  263.     }
  264.     minsize(SSIZE,SSIZE);
  265.     keepaspect(5,4);
  266.     winopen("shad");
  267.     wintitle(computetitle());
  268.     getorigin(&wxorg, &wyorg);
  269.     getsize(&wxsize, &wysize);
  270.     matrixinit();
  271.     shadeinit();
  272.  
  273.     ZNear = getgdesc(GD_ZMIN);
  274.     ZFar = getgdesc(GD_ZMAX);
  275.  
  276.     qdevice(LEFTMOUSE);
  277.     qdevice(MIDDLEMOUSE);
  278.     qdevice(RIGHTMOUSE);
  279.     qdevice(LEFTSHIFTKEY);
  280.     qdevice(LEFTCTRLKEY);
  281.     qdevice(LEFTALTKEY);
  282.     qdevice(TABKEY);
  283.     qdevice(SPACEKEY);
  284.     qdevice(ESCKEY);
  285.     qdevice(QKEY);
  286.     qdevice(WKEY);
  287.     lmenu = defpup("Light Views %t %F|light 1|light 2|light 3",lfunc);
  288.     menu = defpup("Options %t|light views %m|eye view|colored lights toggle|disco mode|quit",lmenu);
  289.     RGBmode();
  290.     doublebuffer();
  291.     gconfig();
  292.  
  293.     subpixel(TRUE);
  294.     zbuffer(TRUE); 
  295.     zfunction(ZF_LEQUAL);
  296.     pixmode(PM_SIZE,16);
  297.     readsource(SRC_ZBUFFER);
  298.  
  299.     cpack(0);
  300.     clear();
  301.     swapbuffers();
  302.     nobjs = 0;
  303.     for(i=firstobj; i<argc; i++) {
  304.     obj[nobjs] = readsgiobj(argv[i]);
  305.      nobjs++;
  306.     }
  307.  
  308.     mytrackztrans(eyetrack,-2.0);
  309.     mytrackrot(eyetrack,0.0,0.0);
  310.  
  311.     setuplight(thelights+0, 30.0,  0.0,-1.5); /* choose z to avoid clipping */
  312.     setuplight(thelights+1, 40.0,120.0,-1.5);
  313.     setuplight(thelights+2, 50.0,240.0,-1.5);
  314.     setuplight(thelights+3, 60.0,270.0,-1.5);
  315.     setlcolors();
  316.     /*frontbuffer(1);*/
  317.  
  318.     tevps = maketevprops(0);
  319.     tevdef(1,0,tevps);
  320.     tevbind(0,1);
  321.  
  322.     gennewshadowmaps();
  323.  
  324.     curlight = 0;
  325.     drawit();
  326.     while (1)  {
  327.     while (qtest())  {
  328.         dev = qread(&val);
  329.         switch (dev)  {
  330.         case QKEY:
  331.             if(val) {
  332.             eye_dz -= 0.0001;
  333.             fprintf(stderr,"eye_dz is %g\n",eye_dz);
  334.             needredraw = 1;
  335.             }
  336.             break;
  337.         case WKEY:
  338.             if(val) {
  339.             eye_dz += 0.0001;
  340.             fprintf(stderr,"eye_dz is %g\n",eye_dz);
  341.             needredraw = 1;
  342.             }
  343.             break;
  344.         case LEFTMOUSE:
  345.             if(val && (!dodisco || !dolightview)) {
  346.             if (!dolightview && getbutton(LEFTSHIFTKEY)) {
  347.                 dotracklight = 1;
  348.                 wintitle(computetitle());
  349.                 curlight = &thelights[curlightnum];
  350.                 mytrackclick(curlight->track);
  351.                 while(getbutton(LEFTMOUSE)) { 
  352.                 mytrackpoll(curlight->track);
  353.                 drawit();
  354.                 }
  355.                 dotracklight = 0;
  356.                 wintitle(computetitle());
  357.                 curlight = 0;
  358.                 needredraw = 1;
  359.             } else {
  360.                 if (dolightview)
  361.                 track = curlight->track;
  362.                 else
  363.                 track = eyetrack;
  364.                 mytrackclick(track);
  365.                 while(getbutton(LEFTMOUSE)) { 
  366.                 mytrackpoll(track);
  367.                 drawit();
  368.                 }
  369.             }
  370.             }
  371.             break;
  372.         case MIDDLEMOUSE:
  373.             if(val && (!dodisco || !dolightview)) {
  374.             if (!dolightview && getbutton(LEFTSHIFTKEY)) {
  375.                 dotracklight = 1;
  376.                 wintitle(computetitle());
  377.                 curlight = &thelights[curlightnum];
  378.                 mytrackclick(curlight->track);
  379.                 while(getbutton(MIDDLEMOUSE)) {
  380.                 mytrackpoll(curlight->track);
  381.                 drawit();
  382.                 }
  383.                 dotracklight = 0;
  384.                 wintitle(computetitle());
  385.                 curlight = 0;
  386.                 needredraw = 1;
  387.             } else {
  388.                 if (dolightview)
  389.                 track = curlight->track;
  390.                 else
  391.                 track = eyetrack;
  392.                 mytrackclick(track);
  393.                 while(getbutton(MIDDLEMOUSE)) {
  394.                 mytrackpoll(track);
  395.                 drawit();
  396.                 }
  397.             }
  398.             }
  399.             break;
  400.         case RIGHTMOUSE:
  401.             if (val) {
  402.                 switch(dopup(menu)) {
  403.                 case MENU_EYEVIEW:
  404.                 if(curlight)
  405.                     newshadowmap(curlight);
  406.                 curlight = 0;
  407.                 dolightview = 0;
  408.                 wintitle(computetitle());
  409.                 break;
  410.                 case MENU_TOGGLECOLOR:
  411.                 coloredlights = coloredlights ? 0 : 1;
  412.                 setlcolors();
  413.                 break;
  414.                 case MENU_DISCO:
  415.                 dodisco = dodisco ? 0 : 1;
  416.                 if (dodisco) {
  417.                     initdiscomode();
  418.                 } else {
  419.                     gennewtransforms();
  420.                     gennewshadowmaps();
  421.                     needredraw = 1;
  422.                 }
  423.                 wintitle(computetitle());
  424.                 break;
  425.                 case MENU_QUIT:
  426.                 exit(0);
  427.             }
  428.             needredraw = 1;
  429.             }
  430.             break;
  431.         case REDRAW:
  432.             reshapeviewport();
  433.             getorigin(&wxorg,&wyorg);
  434.             getsize(&wxsize, &wysize);
  435.             needredraw = 1;
  436.             break;
  437.         case ESCKEY:
  438.             exit(0);
  439.             break;
  440.         default:
  441.             break;
  442.         }
  443.     }
  444.     if (dodisco || needredraw) {
  445.         drawit();
  446.         needredraw = 0;
  447.         if (dodisco) discotimestep();
  448.     }
  449.     }
  450. }
  451.  
  452. initdiscomode()
  453. {
  454. int i;
  455.     
  456.     disco_time = 0.0; /* reset time */
  457.     for(i=0; i<NLIGHTS; i++) {
  458.     thelights[i].disco_track->ztrans = 0.0;
  459.     thelights[i].disco_track->trotx = 0.0;
  460.     thelights[i].disco_track->troty = 0.0;
  461.     thelights[i].disco_track->wiggle = 0.0;
  462.     thelights[i].disco_changed = 1;
  463.     }
  464. }
  465.  
  466. discotimestep()
  467. {
  468. int n,lnum,cycle2,cycle3;
  469. float t;
  470. LightBuffer *lamp;
  471.  
  472.     n = (int)disco_time;
  473.     t = (disco_time-n)/(1.0-disco_step);
  474.     lnum = n % NLIGHTS;
  475.     if (lnum < NLIGHTS)
  476.     lamp = &thelights[lnum];
  477.     else
  478.         lamp = &thelights[0];
  479.     cycle2 = (n % (2*NLIGHTS)) / NLIGHTS;
  480.     cycle3 = (n % (3*NLIGHTS)) / NLIGHTS;
  481.     switch (lnum) {
  482.     case 0:
  483.         lamp->disco_track->wiggle = 25.0*fsin(2.0*M_PI*t);
  484.         lamp->disco_changed = 1;
  485.         break;
  486.     case 1:
  487.         lamp->disco_track->troty = 120.0*(t+cycle3);
  488.         lamp->disco_changed = 1;
  489.         break;
  490.     case 2:
  491.         lamp->disco_track->trotx = (180.0-2.0*lamp->track->trotx)*(cycle2?1.0-t:t);
  492.         lamp->disco_changed = 1;
  493.         break;
  494.     default:
  495.         break;
  496.     }
  497.  
  498.     /* advance eyemat */
  499.     eyetrack->troty += .5;
  500.     if (eyetrack->troty > 360.0)
  501.     eyetrack->troty -= 360.0;
  502.     mygettracktransform(eyetrack,eyemat,inveyemat);
  503.  
  504.     disco_time += disco_step;
  505.     if (disco_time > 100000)
  506.     disco_time = 0.0;
  507. }
  508.  
  509. gennewtransforms()
  510. {
  511. LightBuffer *lamp;
  512. int i;
  513.     for(i=0,lamp=thelights; i<NLIGHTS; i++,lamp++) {
  514.     mygettracktransform(lamp->track,lamp->mat,lamp->invmat);
  515.     }
  516. }
  517.  
  518. gennewshadowmaps()
  519. {
  520. int i;
  521.     for(i=0; i<NLIGHTS; i++) {
  522.     thelights[i].texno = i+1;
  523.     newshadowmap(thelights+i);
  524.     }
  525. }
  526.  
  527. void
  528. newshadowmap(LightBuffer *lightsource)
  529. {
  530.     float *texps;
  531.  
  532.     shadeoff();
  533.     mmode(MVIEWING); /* otherwise, messes up first time */
  534.     loadmatrix(Identity); /* needed, but why? */
  535.     lsetdepth(SHADZNEAR,SHADZFAR);
  536.     viewport(0,SSIZE-1,0,SSIZE-1); 
  537.     czclear(0,SHADZFAR);
  538.     blendfunction(BF_ONE,BF_ZERO);
  539.     zfunction(ZF_LEQUAL);
  540.     ortho(-.5,SSIZE-.5,-.5,SSIZE-.5,-1,1);
  541.     loadmatrix(Identity); /* needed, but why? */
  542.     cpack(0xff00);
  543.     myrectf(0,0,SSIZE-1,SSIZE-1,1); /* draw 2-pixel wide border with z=SHADZNEAR */
  544.     myrectf(1,1,SSIZE-2,SSIZE-2,1);
  545.     viewport(2,SSIZE-3,2,SSIZE-3); /* render real shadow map inside */
  546.     fromlight(lightsource->mat);
  547.     getmatrix(lightsource->texm);
  548.     if (dozdisplace) 
  549.     shadowdisplacez(1);
  550.     drawmodel();
  551.     if (dozdisplace) 
  552.     shadowdisplacez(0);
  553.  
  554.     texps = maketexprops(dobicubic,dofastread);
  555.     if (!dofastread) {
  556.     lrectread(0,0,SSIZE-1,SSIZE-1,lightsource->smap);
  557.     texdef2d(lightsource->texno,1,SSIZE,SSIZE,
  558.         (unsigned long *)lightsource->smap,0,texps);
  559.     } else {
  560.     texdef2d(lightsource->texno,1,SSIZE,SSIZE,NULL,0,texps);
  561.     texbind(0,lightsource->texno);
  562.     }
  563.     viewport(0,wxsize-1,0,wysize-1); 
  564. }
  565.  
  566. /*
  567.  *  maps clip space x,y from a [-1,1] range to [0,1] range, which
  568.  *  is the range s,t should be.
  569.  */
  570. float specialmat[4][4] =  {
  571.     0.5, 0.0, 0.0, 0.0,
  572.     0.0, 0.5, 0.0, 0.0,
  573.     0.0, 0.0, 1.0, 0.0,
  574.     0.5, 0.5, 0.0, 1.0,
  575. };
  576.  
  577. texsetup(lightsource,inveye)
  578. LightBuffer *lightsource;
  579. float inveye[4][4];
  580. {
  581.     float p[4];
  582.  
  583.     /*
  584.      *  set up texture matrix, but first, make sure ModelView is Identity
  585.      *    so S,T,R,Q plane eqs are the same.  Remember, texgen(TG_CONTOUR)
  586.      *    will xform the plane eqs by that ModelView matrix.
  587.      */
  588.     pushmatrix();
  589.     loadmatrix(Identity);
  590.     mmode(MTEXTURE);
  591.     loadmatrix(Identity);
  592.     translate(0.0,0.0,32768.0);
  593.     scale(1.0,1.0,32767.5);
  594.     translate(0.0,0.0,eye_dz);
  595.  
  596.     multmatrix(specialmat);
  597.     multmatrix(lightsource->texm); 
  598.     multmatrix(inveye);
  599.  
  600.     p[0] = 1.0; p[1] = 0; p[2] = 0; p[3] = 0;
  601.     texgen(TX_S,TG_CONTOUR,p);
  602.     p[0] = 0.0; p[1] = 1; p[2] = 0; p[3] = 0;
  603.     texgen(TX_T,TG_CONTOUR,p);
  604.     p[0] = 0.0; p[1] = 0; p[2] = 1; p[3] = 0;
  605.     texgen(TX_R,TG_CONTOUR,p);
  606.     p[0] = 0.0; p[1] = 0; p[2] = 0; p[3] = 1;
  607.     texgen(TX_Q,TG_CONTOUR,p);
  608.     texgen(TX_S,TG_ON,0);
  609.     texgen(TX_T,TG_ON,0);
  610.     texgen(TX_R,TG_ON,0);
  611.     texgen(TX_Q,TG_ON,0);
  612.     mmode(MVIEWING); /* clean up after texsetup() */
  613.     popmatrix();
  614. }
  615.  
  616. drawit()
  617. {
  618.     LightBuffer *lamp;
  619.     int i,j;
  620.     float *tevps;
  621.  
  622.     if (!dolightview) {
  623.     if (dotracklight) {
  624.         mygettracktransform(curlight->track,curlight->mat,curlight->invmat);
  625.         newshadowmap(curlight);
  626.     } else {
  627.         mygettracktransform(eyetrack,eyemat,inveyemat);
  628.     }
  629.     }
  630.  
  631.     if (dodisco) {
  632.     for(i=0,lamp=thelights; i<NLIGHTS; i++,lamp++) {
  633.         if (lamp->disco_changed) {
  634.         mygetdiscotransform(lamp->track,lamp->disco_track,lamp->mat,lamp->invmat);
  635.         newshadowmap(lamp);
  636.         lamp->disco_changed = 0;
  637.         }
  638.     }
  639.     }
  640.  
  641.     lsetdepth(ZNear,ZFar);
  642.     czclear(BACKCOLOR,ZFar);
  643.  
  644.     blendfunction(BF_ONE,BF_ZERO);
  645.     zfunction(ZF_LEQUAL);
  646.     if (dolightview) {
  647.     mmode(MVIEWING);
  648.     perspective((int)(light_fov*20),5.0/4.0,light_near,light_far);
  649.     loadmatrix(Identity);
  650.     pushmatrix();
  651.         if (!dodisco)
  652.         mygettracktransform(curlight->track,curlight->mat,curlight->invmat);
  653.         multmatrix(curlight->mat);
  654.         positionlight(curlight->invmat); /* hack to get light at 0,0,0 */
  655.         shadeon();
  656.         setspecular(SPECSCALE,SPECSCALE,SPECSCALE);
  657.         setdiffuse(.6,.6,.6);
  658.         drawmodel();
  659.         shadeoff();
  660.     popmatrix();
  661.     } else {
  662.     mmode(MVIEWING);
  663.     perspective((int)(eye_fov*20),5.0/4.0,eye_near,eye_far);
  664.     loadmatrix(eyemat);
  665.     lamp = thelights;
  666.     for(i=0; i<NLIGHTS; i++) {
  667.         texsetup(lamp,inveyemat);
  668.         if(i==0) {
  669.         zfunction(ZF_LEQUAL);
  670.         blendfunction(BF_ONE,BF_ZERO);
  671.         } else {
  672.         zfunction(ZF_EQUAL);
  673.         blendfunction(BF_ONE,BF_ONE);
  674.         }
  675.         pushmatrix();
  676.         positionlight(lamp->invmat);
  677.         mysettexture(lamp->texno);
  678.         shadeon();
  679.         setspecular(SPECSCALE/NLIGHTS,SPECSCALE/NLIGHTS,SPECSCALE/NLIGHTS);
  680.         setdiffuse(lamp->r,lamp->g,lamp->b);
  681.         drawmodel();
  682.         shadeoff();
  683.         mysettexture(0);
  684.         popmatrix();
  685.         lamp++;
  686.       }
  687.     }
  688.  
  689.     swapbuffers();
  690. }
  691.  
  692. void
  693. shadowdisplacez(int mode)
  694. {
  695.     if (mode)
  696.     displacepolygon(1.0);
  697.     else
  698.     displacepolygon(0.0);
  699. }
  700.  
  701. void
  702. fromlight(float mat[4][4])
  703. {
  704.     float m[4][4];
  705.  
  706.     mmode(MSINGLE);
  707.     pushmatrix();
  708.     perspective((int)(light_fov*20),1.0,light_near,light_far);
  709.     multmatrix(mat);
  710.     getmatrix(m);
  711.     popmatrix();
  712.     multmatrix(m);
  713. }
  714.  
  715. drawmodel()
  716. {
  717. int i;
  718. LightBuffer *lt;
  719.  
  720.     cpack(0xffffffff);
  721.  
  722.     if (dodrawlights) {
  723.     lt = thelights;
  724.     for (i=0; i<NLIGHTS; i++) {
  725.         drawlight(lt++);
  726.     }
  727.     }
  728.  
  729.     for(i=0; i<nobjs; i++) {
  730.     drawsgiobj(obj[i],DRAW_POINTS|DRAW_NORMALS);
  731.     }
  732.     lmcolor(LMC_COLOR);
  733. }
  734.  
  735. float *pack3f(float x,float y,float z)
  736. {
  737. static float v[3];
  738.     v[0] = x;
  739.     v[1] = y;
  740.     v[2] = z;
  741.     return v;
  742. }
  743.  
  744. /*
  745.  *  draws 6 faces of a box.
  746.  *  the face that looks down the -z axis is colored according
  747.  *  to the light's color.
  748.  */
  749. void
  750. drawlight(LightBuffer *lt)
  751. {
  752. #define DEG2RAD (M_PI/180.0)
  753. float x,y,z;
  754. float imat[4][4];
  755.  
  756.     x = light_near*fsin(DEG2RAD*light_fov);
  757.     y = x;
  758.     z = -(light_near-.01);
  759.  
  760.     pushmatrix();
  761.     invertmat(lt->mat,imat);
  762.     multmatrix(imat);
  763.     bgntmesh();
  764.     n3f(pack3f(0,0,1));
  765.     v3f(pack3f(-x,-y,0)); /* v0 */
  766.     v3f(pack3f(x,-y,0));  /* v1 */
  767.     v3f(pack3f(-x,y,0));  /* v3 */
  768.     v3f(pack3f(x,y,0));   /* v2 */
  769.     endtmesh();
  770.     bgntmesh();
  771.     n3f(pack3f(1,0,0));
  772.     v3f(pack3f(x,-y,0));  /* v1 */
  773.     v3f(pack3f(x,-y,z));  /* v5 */
  774.     v3f(pack3f(x,y,0));   /* v2 */
  775.     v3f(pack3f(x,y,z));   /* v6 */
  776.     endtmesh();
  777.     bgntmesh();
  778.     n3f(pack3f(-1,0,0));
  779.     v3f(pack3f(-x,-y,z)); /* v4 */
  780.     v3f(pack3f(-x,-y,0)); /* v0 */
  781.     v3f(pack3f(-x,y,z));  /* v7 */
  782.     v3f(pack3f(-x,y,0));  /* v3 */
  783.     endtmesh();
  784.     bgntmesh();
  785.     n3f(pack3f(0,-1,0));
  786.     v3f(pack3f(-x,-y,0)); /* v0 */
  787.     v3f(pack3f(-x,-y,z)); /* v4 */
  788.     v3f(pack3f(x,-y,0));  /* v1 */
  789.     v3f(pack3f(x,-y,z));  /* v5 */
  790.     endtmesh();
  791.     bgntmesh();
  792.     n3f(pack3f(0,1,0));
  793.     v3f(pack3f(x,y,0));   /* v2 */
  794.     v3f(pack3f(x,y,z));   /* v6 */
  795.     v3f(pack3f(-x,y,0));  /* v3 */
  796.     v3f(pack3f(-x,y,z));  /* v7 */
  797.     endtmesh();
  798.  
  799.     bgntmesh();
  800.     n3f(pack3f(0,0,-1));
  801.     c3f(pack3f(lt->r,lt->g,lt->b));
  802.     v3f(pack3f(x,-y,z));   /* v5 */
  803.     v3f(pack3f(-x,-y,z));  /* v4 */
  804.     v3f(pack3f(x,y,z));    /* v6 */
  805.     v3f(pack3f(-x,y,z));   /* v7 */
  806.     endtmesh();
  807.  
  808.     popmatrix();
  809. }
  810.  
  811. void
  812. myrectf(float x1,float y1,float x2,float y2,float z)
  813. {
  814.     bgnline();
  815.     v3f(pack3f(x1,y1,z));
  816.     v3f(pack3f(x2+1,y1,z));
  817.     endline();
  818.     bgnline();
  819.     v3f(pack3f(x2,y1,z));
  820.     v3f(pack3f(x2,y2+1,z));
  821.     endline();
  822.     bgnline();
  823.     v3f(pack3f(x1,y1,z));
  824.     v3f(pack3f(x1,y2+1,z));
  825.     endline();
  826.     bgnline();
  827.     v3f(pack3f(x1,y2,z));
  828.     v3f(pack3f(x2+1,y2,z));
  829.     endline();
  830. }
  831.  
  832. float *maketexprops(int dobicubic,int dofastread)
  833. {
  834.     static float texps[32];
  835.     int i = 0;
  836.  
  837.     if (dobicubic) {
  838.     texps[i++] = TX_MAGFILTER;
  839.     texps[i++] = TX_BICUBIC_GEQUAL;
  840.     texps[i++] = TX_MINFILTER;
  841.     texps[i++] = TX_BICUBIC_GEQUAL;
  842.     } else {
  843.     texps[i++] = TX_MAGFILTER;
  844.     texps[i++] = TX_BILINEAR_GEQUAL;
  845.     texps[i++] = TX_MINFILTER;
  846.     texps[i++] = TX_BILINEAR_GEQUAL;
  847.     }
  848.     texps[i++] = TX_WRAP;
  849.     texps[i++] = TX_CLAMP;
  850.     texps[i++] = TX_INTERNAL_FORMAT;
  851.     texps[i++] = TX_I_16;
  852.     if (dofastread) {
  853.     texps[i++] = TX_FRAMEBUFFER_SRC;
  854.     texps[i++] = 0.0;
  855.     texps[i++] = 0.0;
  856.     texps[i++] = wxsize-1;
  857.     texps[i++] = wysize-1;
  858.     } else {
  859.     texps[i++] = TX_EXTERNAL_FORMAT;    /* is this stuff necessary? */
  860.     texps[i++] = TX_PACK_16;
  861.     texps[i++] = TX_NOCOPY; /* undocumented, but makes it quite fast */
  862.     }
  863.     texps[i++] = TX_NULL;
  864.  
  865.     return texps;
  866. }
  867.  
  868. float *maketevprops(int doalpha)
  869. {
  870.     static float tevps[32];
  871.     int i = 0;
  872.  
  873.     if (doalpha) {
  874.     tevps[i++] = TV_ALPHA;
  875.     } else {
  876.     tevps[i++] = TV_MODULATE;
  877.     tevps[i++] = TV_COLOR;
  878.     tevps[i++] = 1.0;
  879.     tevps[i++] = 1.0;
  880.     tevps[i++] = 1.0;
  881.     tevps[i++] = 0.0;
  882.     }
  883.     tevps[i++] = TX_NULL;
  884.  
  885.     return tevps;
  886. }
  887.  
  888.  
  889. mysettexture(n)
  890. int n;
  891. {
  892.     if(n==0) {
  893.         texbind(0,0);
  894.     } else {
  895.         texbind(0,n);
  896.     }
  897. }
  898.  
  899.  
  900. static float oztrans;
  901. static float otrotx, otroty;
  902. static float trx, try;
  903. static int dotrans;
  904.  
  905. float fgetmousex()
  906. {
  907.     return ((float)getvaluator(MOUSEX)-wxorg)/(float)wxsize;
  908. }
  909.  
  910. float fgetmousey()
  911. {
  912.     return ((float)getvaluator(MOUSEY)-wyorg)/(float)wysize;
  913. }
  914.  
  915. void
  916. mytrackztrans(TrackState *ts,float z)
  917. {
  918.     ts->ztrans = z;
  919. }
  920.  
  921. void
  922. mytrackrot(TrackState *ts,float x,float y)
  923. {
  924.     ts->trotx = x;
  925.     ts->troty = y;
  926. }
  927.  
  928. void
  929. mytrackclick(TrackState *ts)
  930. {
  931.     trx = fgetmousex();
  932.     try = fgetmousey();
  933.     if(getbutton(MIDDLEMOUSE))
  934.     dotrans = 1;
  935.     else
  936.     dotrans = 0;
  937.     oztrans = ts->ztrans;
  938.     otrotx = ts->trotx;
  939.     otroty = ts->troty;
  940. }
  941.  
  942. void
  943. mytrackpoll(TrackState *ts)
  944. {
  945.     if(dotrans) {
  946.     ts->ztrans = oztrans+3.0*(fgetmousey()-try);
  947.     } else {
  948.     ts->trotx = otrotx+90.0*(fgetmousey()-try);
  949.     ts->troty = otroty+360.0*(fgetmousex()-trx);
  950.     }
  951. }
  952.  
  953. void
  954. mygettracktransform(TrackState *ts,float mat[4][4],float invmat[4][4])
  955. {
  956.     pushmatrix();
  957.     loadmatrix(Identity);        
  958.     pushmatrix();
  959.     translate(0.0,0.0,ts->ztrans);
  960.     rot(ts->trotx,'x');
  961.     rot(ts->troty,'y');
  962.     getmatrix(mat);
  963.  
  964.     /* compute inverse by reversing transforms */
  965.     popmatrix();
  966.     rot(-ts->troty,'y');
  967.     rot(-ts->trotx,'x');
  968.     translate(0.0,0.0,-ts->ztrans);
  969.     getmatrix(invmat);
  970.     popmatrix();
  971. }
  972.  
  973. void
  974. mygetdiscotransform(TrackState *ts,TrackState *ts2,float mat[4][4],float invmat[4][4])
  975. {
  976.     pushmatrix();
  977.     loadmatrix(Identity);        
  978.     pushmatrix();
  979.     rot(ts2->wiggle,'y');
  980.     translate(0.0,0.0,ts->ztrans+ts2->ztrans);
  981.     rot(ts->trotx+ts2->trotx,'x');
  982.     rot(ts->troty+ts2->troty,'y');
  983.     getmatrix(mat);
  984.  
  985.     /* compute inverse by reversing transforms */
  986.     popmatrix();
  987.     rot(-(ts->troty+ts2->troty),'y');
  988.     rot(-(ts->trotx+ts2->trotx),'x');
  989.     translate(0.0,0.0,-(ts->ztrans+ts2->ztrans));
  990.     rot(-ts2->wiggle,'y');
  991.     getmatrix(invmat);
  992.     popmatrix();
  993. }
  994.  
  995. char *computetitle()
  996. {
  997. static char s[100];
  998. static char ls[100];
  999. char *p;
  1000.  
  1001.     ls[0] = 0;
  1002.     p = ls;
  1003.     if (dodisco) {
  1004.     sprintf(p,"- disco mode ");
  1005.     p += strlen(p);
  1006.     }
  1007.     if (dolightview) {
  1008.     sprintf(p,"- view from light %d",curlightnum+1);
  1009.     }
  1010.     else if (dotracklight) {
  1011.     sprintf(p,"- tracking light %d",curlightnum+1);
  1012.     }
  1013.     sprintf(s,"%s %s",WINTITLESTR,ls);
  1014.     return s;
  1015. }
  1016.